package neuronvisualizer;

/**

 * ParseNeurons class
 * @author  John Newsom
 * 
 * This class will parse the data from the neurons.txt file
 * and then output an excerpt of java code that will construct
 * a hashmap of all the neurons, enabling us to refer to the 
 * neurons by their IDs in the simulator.
 */
 
 import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.SimpleVector;
 
 
 class NeuronParser{
	private boolean doingConnections;
	private Driver parent;
	private String readPath;
	private float aveX;
	private float aveY;
	private float aveZ;
	private Connection[] connections;

	private double maxCharge=0;
	private double minCharge =0;
	private float maxX=0;
	private float minX=0;
	private float maxY=0;
	private float minY=0;
	private float maxZ=0;
	private float minZ=0;
	private int totalConnect;
	
	
	private ArrayList<Neuron> neurons;
	
	public NeuronParser(Driver parent,String f){
		this.parent = parent;
		neurons = new ArrayList<Neuron>();
		doingConnections = true;
		readPath=f;
	}
	
	public void beginParse(){	
		File readFrom = new File(readPath);
		BufferedReader reader = null;
		String inLine="";
		
		try{
			reader = new BufferedReader(new FileReader(readFrom));
			inLine = reader.readLine();
		} catch(Exception e){e.printStackTrace();}
		
		StringTokenizer st;
		
		/**
		* The following variables are the components that make up a neuron for the simulator
		*/
		int ID = 0;
		totalConnect=0;
		Type neuronType = null;
		Object3D model = null;
		Layer layer;
		int xPos = 0;
		int yPos = 0;
		int zPos = 0;	
		
		int totalX=0;
		int totalY=0;
		int totalZ=0;
		
		boolean first = true;
		try{
		while(inLine!=null){

				st = new StringTokenizer(inLine);
				
				ID = Integer.parseInt(st.nextToken());
				
				String s = st.nextToken();
				if(s.equals("RS")){
					neuronType = Type.RS;
				}
				else if(s.equals("FS")){
					neuronType = Type.FS;
				}
				else if(s.equals("LTS")){
					neuronType = Type.LTS;
				}
				else if(s.equals("IB")){
					neuronType = Type.IB;
				}

				else
					System.err.print("Error: Unknown neuron type in input file");
				String layerstring = st.nextToken();
				if (layerstring.equals("II")){
					layer = Layer.II;
				}
				else if (layerstring.equals("III")){
					layer = Layer.III;
				}
				else if (layerstring.equals("IV")){
					layer = Layer.IV;
				}
				else if (layerstring.equals("V")){
					layer = Layer.V;
				}
				else{
					layer = Layer.VI;
				}
				xPos = (int)(Integer.parseInt(st.nextToken())*parent.getScale());
				zPos = (int)(Integer.parseInt(st.nextToken())*parent.getScale());
				yPos = (int)((Integer.parseInt(st.nextToken()) * -1)*parent.getScale());
				
				
				if(first){
					maxX = xPos;
					minX = xPos;
					maxY = yPos;
					minY = yPos;
					maxZ = zPos;
					minZ = zPos;
					first = false;
				}
				if(xPos > maxX){
					maxX = xPos;
				}
				if(xPos < minX){
					minX = xPos;
				}
				//MAXY AND MINY ARE SWITCHED BECAUSE THE 3D LIBRARY USES NEGATIVE Y VALUES TO GO UP
				if(yPos < maxY){
					maxY = yPos;
				}
				if(yPos > minY){
					minY = yPos;
				}
				if(zPos > maxZ){
					maxZ = zPos;
				}
				if(zPos < minZ){
					minZ = zPos;
				}
				
				totalX+=xPos;
				totalY+=yPos*-1;
				totalZ+=zPos;
				if(doingConnections)
					connections = new Connection[st.countTokens()/2];
				int count = 0;
				/**
				 * Adds all the remaining values in the readLine to the list of connections
				 */
				if(doingConnections){
					while(st.hasMoreTokens()){
					    	int connectionID = Integer.parseInt(st.nextToken());
					    	double charge = Double.parseDouble(st.nextToken());
					    	if(charge>maxCharge){
					    	    maxCharge = charge;
					    	}
					    	else if(charge<minCharge){
					    	    minCharge = charge;
					    	}
						Connection c = new Connection(ID,connectionID,charge);
						connections[count]=c;
						count++;
					
					}
				}	
				
				/**
				 * Starts building a temporary neuron which will then be added to the
				 * list of neurons in Simulator parent.
				 */
			
				Neuron tempNeuron = new Neuron(parent,ID,neuronType,layer,xPos,yPos,zPos,connections);
				totalConnect+=connections.length;
				neurons.add(tempNeuron);
				inLine=reader.readLine();
				
			}
		}
		catch(Exception e){e.printStackTrace();}

		int total = neurons.size();
		
		aveX=totalX/total;
		aveY=totalY/total;
		aveZ=totalZ/total;
		
		Neuron.maxCharge = (float) maxCharge;
		Neuron.minCharge = (float) minCharge;
		
		try{
			reader.close();
		}catch(Exception e){e.printStackTrace();}
		
		
		
	}
	
	public void sendToDriver(){
		parent.initializeNeuronArray(neurons.size(),totalConnect);
		for(Neuron tempNeuron:neurons){
			parent.addNeuron(tempNeuron);
		}	
		
		parent.setMidpoint(new SimpleVector(aveX,aveZ,aveY));
		
	}
	public float getMaxY(){
		return maxY;
	}
	public float getMinY(){
		return minY;
	}
	public float getMaxX(){
		return maxX;
	}
	public float getMinX(){
		return minX;
	}
	public float getMaxZ(){
		return maxZ;
	}
	public float getMinZ(){
		return minZ;
	}
	public float getMaxCharge(){
	    return (float)maxCharge;
	}	
	public float getMinCharge(){
	    return (float)minCharge;
	}
	
	
 }//END CLASS PARSENEURONS